﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CodeDDD.Domain.Seedwork;
using System.Data.Entity;
using System.Data;

namespace CodeDDD.Infrastructure.Data.EntityFramework
{
    public class EFUnitOfWork
        : DbContext, IUnitOfWork
    {
        #region Constructor

        public EFUnitOfWork() { }

        #endregion

        #region Members

        public IDbSet<TEntity> CreateSet<TEntity>() where TEntity : class
        {
            return base.Set<TEntity>();
        }

        public void Attach<TEntity>(TEntity item) where TEntity : class
        {
            // attach and set as unchanged
            base.Entry<TEntity>(item).State = System.Data.EntityState.Unchanged;
        }

        public void SetModified<TEntity>(TEntity item) where TEntity : class
        {
            // this operation also attach item in object state manager
            base.Entry<TEntity>(item).State = System.Data.EntityState.Modified;
        }

        #endregion

        #region IUnitOfWork Members

        public void BeginWork() { }

        public void Commit()
        {
            try
            {
                // Call DBContext Save changes 
                base.SaveChanges();
            }
            catch (OptimisticConcurrencyException)
            {
                // http://msdn.microsoft.com/en-us/library/bb336792.aspx

                // Resolve the concurrency conflict by refreshing the 
                // object context before re-saving changes. 
                // this.Refresh(RefreshMode.ClientWins, orders);

                // Save changes.
                // this.SaveChanges();

                throw;
            }
        }

        public void RollbackChanges()
        {
            // set all entities in change tracker 
            // as 'unchanged state'
            base.ChangeTracker.Entries()
                              .ToList()
                              .ForEach(entry => entry.State = System.Data.EntityState.Unchanged);
        }

        #endregion
    }
}
